#!/usr/bin/env bash
set -e

header_pattern='[0-9]+\.\.[0-9]+'
IFS= read -r header

if [[ "$header" =~ $header_pattern ]]; then
  count="${header:3}"
  index=0
  failures=0
  skipped=0
  name=
  count_column_width=$(( ${#count} * 2 + 2 ))
else
  # If the first line isn't a TAP plan, print it and pass the rest through
  printf '%s\n' "$header"
  exec cat
fi

update_screen_width() {
  screen_width="$(tput cols)"
  count_column_left=$(( $screen_width - $count_column_width ))
}

trap update_screen_width WINCH
update_screen_width

begin() {
  go_to_column 0
  buffer_with_truncation $(( $count_column_left - 1 )) '   %s' "$name"
  clear_to_end_of_line
  go_to_column $count_column_left
  buffer "%${#count}s/${count}" "$index"
  go_to_column 1
}

pass() {
  go_to_column 0
  buffer ' ✓ %s' "$name"
  advance
}

skip() {
  local reason="$1"
  if [[ -n "$reason" ]]; then
    reason=": $reason"
  fi
  go_to_column 0
  buffer ' - %s (skipped%s)' "$name" "$reason"
  advance
}

fail() {
  go_to_column 0
  set_color 1 bold
  buffer ' ✗ %s' "$name"
  advance
}

log() {
  set_color 1
  buffer '   %s\n' "$1"
  clear_color
}

summary() {
  buffer '\n%d test' "$count"
  if [[ "$count" -ne 1 ]]; then
    buffer 's'
  fi

  buffer ', %d failure' "$failures"
  if [[ "$failures" -ne 1 ]]; then
    buffer 's'
  fi

  if [[ "$skipped" -gt 0 ]]; then
    buffer ', %d skipped' "$skipped"
  fi

  buffer '\n'
}

buffer_with_truncation() {
  local width="$1"
  shift
  local string

  printf -v 'string' -- "$@"

  if [[ "${#string}" -gt "$width" ]]; then
    buffer '%s...' "${string:0:$(( $width - 4 ))}"
  else
    buffer '%s' "$string"
  fi
}

go_to_column() {
  local column="$1"
  buffer '\x1B[%dG' $(( $column + 1 ))
}

clear_to_end_of_line() {
  buffer '\x1B[K'
}

advance() {
  clear_to_end_of_line
  buffer '\n'
  clear_color
}

set_color() {
  local color="$1"
  local weight=22

  if [[ "$2" == 'bold' ]]; then
    weight=1
  fi
  buffer '\x1B[%d;%dm' "$(( 30 + $color ))" "$weight"
}

clear_color() {
  buffer '\x1B[0m'
}

_buffer=

buffer() {
  local content
  printf -v content -- "$@"
  _buffer+="$content"
}

flush() {
  printf '%s' "$_buffer"
  _buffer=
}

finish() {
  flush
  printf '\n'
}

trap finish EXIT

while IFS= read -r line; do
  case "$line" in
  'begin '* )
    ((++index))
    name="${line#* $index }"
    begin
    flush
    ;;
  'ok '* )
    skip_expr="ok $index (.*) # skip ?(([[:print:]]*))?"
    if [[ "$line" =~ $skip_expr ]]; then
      ((++skipped))
      skip "${BASH_REMATCH[2]}"
    else
      pass
    fi
    ;;
  'not ok '* )
    ((++failures))
    fail
    ;;
  '# '* )
    log "${line:2}"
    ;;
  esac
done

summary
